﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Data;
using System.Windows.Resources;
using System.ComponentModel;
using VIBlend.WPF.Controls;
using System.Reflection;
using System.Windows.Controls.Primitives;
using System.Windows.Threading;

namespace AnonsaiWPF.CSharp.DataGridViewDemos
{
    [Category("VIBlend.WPF.Examples")]
    public partial class SpreadSheet : Window, IWindow
    {
        DataTemplate cellEditTextBoxTemplate;
        TextBox textBox;
        ScrollBar hScrollBar;
        ScrollBar vScrollBar;
        Key pressedKey;
        DispatcherTimer timer = new DispatcherTimer();
        public void SetTheme()
        {
            dataGrid.FontFamily = new FontFamily("Tahoma");
        }
  
        #region IWindow Members

        public void DetachContent()
        {
            RemoveLogicalChild(Content);
        }

        public Grid Root
        {
            get
            {
                return this.LayoutRoot;
            }
        }
        #endregion

        public SpreadSheet()
        {
            InitializeComponent();

            timer.Tick += new EventHandler(timer_Tick);
            this.InitializeGrid();
        }

        void timer_Tick(object sender, EventArgs e)
        {
            this.UpdateVerticalScrollTooltip();             
        }

        private void InitializeGrid()
        {
            this.cellEditTextBoxTemplate = this.Resources["cellEditTextBoxTemplate"] as DataTemplate;
            EditorActivationFlags activationFlags =  EditorActivationFlags.MOUSE_DBLCLICK | EditorActivationFlags.MOUSE_CLICK_SELECTED_CELL;
            Style hierarchyItemElementStyle = (Style)this.LayoutRoot.Resources["ItemStyle"];
            this.dataGrid.RowsHierarchy.HierarchyItemDefaultStyle = hierarchyItemElementStyle;
            this.dataGrid.ColumnsHierarchy.HierarchyItemDefaultStyle = hierarchyItemElementStyle;
            dataGrid.CellsArea.DefaultCellStyle = (Style)this.LayoutRoot.Resources["Office2010SilverGridCellElementStyle"];
            dataGrid.VerticalScrollBarStyle = (Style)this.LayoutRoot.Resources["Office2010SilverScrollBarStyle"];
            dataGrid.HorizontalScrollBarStyle = (Style)this.LayoutRoot.Resources["Office2010SilverScrollBarStyle"];

            // Creates Rows and Columns.
            int i = 0;
            while (i < 26)
            {
                int newCh = (int)'A' + i;
                char ch = (char)newCh;
                HierarchyItem item = this.dataGrid.ColumnsHierarchy.Items.Add(ch.ToString());
                item.Width = 64;
                item.CellEditTemplate = this.cellEditTextBoxTemplate;
                item.CellEditorActivationFlags = activationFlags;
                item.CellEditorDeActivationFlags = EditorActivationFlags.MOUSE_CLICK;
                 
                i++;
            }

            i = 1;
            while (i < 100)
            {
                HierarchyItem item = this.dataGrid.RowsHierarchy.Items.Add(i.ToString());
                item.Width = 32;
                
                i++;
            }

            this.dataGrid.IsManualEditUpdateModeEnabled = true;
            this.dataGrid.Refresh();
            dataGrid.CellEditorDeActivated += new VIBlend.WPF.Controls.DataGrid.CellEventHandler(dataGrid1_CellEditorDeActivated);
            dataGrid.CellEditorActivated += new VIBlend.WPF.Controls.DataGrid.CellEventHandler(dataGrid1_CellEditorActivated);
            dataGrid.PreviewKeyDown += new KeyEventHandler(dataGrid1_PreviewKeyDown);

            this.dataGrid.GetScrollbars(out hScrollBar, out vScrollBar);

            hScrollBar.ValueChanged += new RoutedPropertyChangedEventHandler<double>(hScrollBar_ValueChanged);
            vScrollBar.ValueChanged += new RoutedPropertyChangedEventHandler<double>(vScrollBar_ValueChanged);
            hScrollBar.LostMouseCapture += new MouseEventHandler(hScrollBar_LostMouseCapture);
            vScrollBar.LostMouseCapture += new MouseEventHandler(vScrollBar_LostMouseCapture);

            this.dataGrid.CellMouseClick += new VIBlend.WPF.Controls.DataGrid.CellMouseButtonEventHandler(dataGrid_CellMouseClick);
            this.dataGrid.NavigationKeyDown += new KeyEventHandler(dataGrid_NavigationKeyDown);
            this.dataGrid.MouseMove += new MouseEventHandler(dataGrid_MouseMove);
            this.dataGrid.AllowCopy = true;
            this.dataGrid.AllowPaste = true;
            this.dataGrid.CellKeyDown += new VIBlend.WPF.Controls.DataGrid.CellKeyEventHandler(dataGrid_CellKeyDown);
        }

        void dataGrid_CellKeyDown(object sender, CellKeyEventArgs args)
        {
            if (args.KeyEventArgs.Key == Key.Delete && args.Cell != null)
            {
                foreach (GridCell cell in this.dataGrid.CellsArea.SelectedCells)
                {
                    cell.Value = "";
                }
                this.dataGrid.Refresh();
            }
        }

        DateTime toolTipUpdate;

        // Closes the scrolling tooltip when the user moves the mouse cursor.
        void dataGrid_MouseMove(object sender, MouseEventArgs e)
        {
            TimeSpan span = DateTime.Now - toolTipUpdate;

            if (this.hScrollBar.IsMouseCaptureWithin || this.vScrollBar.IsMouseCaptureWithin)
            {
                  return;
            }

            if (!this.hScrollBar.IsMouseCaptureWithin && !this.vScrollBar.IsMouseCaptureWithin)
            {
                this.timer.Stop();
            }

            if (span.TotalSeconds < 3)
                return;

            if (this.scrollingToolTip.IsOpen)
            {
                this.scrollingToolTip.IsOpen = false;
            }

            this.timer.Stop();
        }

        // Sets the selected cell combo box value.
        void dataGrid_NavigationKeyDown(object sender, KeyEventArgs e)
        {
            if (this.dataGrid.CellsArea.SelectedCellsCount > 0)
            {
                GridCell cell = this.dataGrid.CellsArea.SelectedCells[0];
                if (cell != null)
                {
                    string text = cell.ColumnItem.Text + cell.RowItem.Text;
                    this.SelectedCellComboBox.Text = text;
                }
            }
        }

        // Sets the selected cell combo box value.
        void dataGrid_CellMouseClick(object sender, CellMouseButtonEventArgs args)
        {
            GridCell cell = args.Cell;
            if (cell != null)
            {
                string text = cell.ColumnItem.Text + cell.RowItem.Text;
                this.SelectedCellComboBox.Text = text;
            }
        }

        // Close the scrolling tooltip if the vScrollBar is not captured.
        void vScrollBar_LostMouseCapture(object sender, MouseEventArgs e)
        {
            this.scrollingToolTip.IsOpen = false;
            this.timer.Stop();
        }

        // Close the scrolling tooltip if the hScrollBar is not captured.
        void hScrollBar_LostMouseCapture(object sender, MouseEventArgs e)
        {
            this.scrollingToolTip.IsOpen = false;
        }

        private ToolTip scrollingToolTip = new ToolTip();

        // Updates and opens the scrolling tooltip.
        void vScrollBar_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (!this.timer.IsEnabled)
            {
                this.timer.Start();
            }

            this.UpdateVerticalScrollTooltip();
        }

        // Initialize and open the tooltip.
        private void UpdateVerticalScrollTooltip()
        {
            this.toolTipUpdate = DateTime.Now;

            Rect viewPort = this.dataGrid.CellsArea.ViewPort;
            HierarchyItem startRow = null;

            for (int i = 0; i < this.dataGrid.RowsHierarchy.Items.Count; i++)
            {
                HierarchyItem item = this.dataGrid.RowsHierarchy.Items[i];
                if (item.DrawBounds.Y < viewPort.Top)
                    continue;
                else
                {
                    startRow = item;
                    break;
                }
            }

            if (startRow != null)
            {
                this.scrollingToolTip.Placement = PlacementMode.Left;
                this.scrollingToolTip.PlacementTarget = this.vScrollBar;
                this.scrollingToolTip.HorizontalOffset = 0;
                this.scrollingToolTip.VerticalOffset = this.dataGrid.ActualHeight / 2;
                this.scrollingToolTip.Content = "Row: " + startRow.Text;
                this.scrollingToolTip.IsOpen = true;
            }
        }

        // shows the scrolling tooltip for the HScrollBar.
        void hScrollBar_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            this.toolTipUpdate = DateTime.Now;

            Rect viewPort = this.dataGrid.CellsArea.ViewPort;
            HierarchyItem startColumn = null;

            for (int i = 0; i < this.dataGrid.ColumnsHierarchy.Items.Count; i++)
            {
                HierarchyItem item = this.dataGrid.ColumnsHierarchy.Items[i];
                if (item.DrawBounds.X < viewPort.Left)
                    continue;
                else
                {
                    startColumn = item;
                    break;
                }
            }

            if (startColumn != null)
            {
                this.scrollingToolTip.Placement = PlacementMode.Top;
                this.scrollingToolTip.PlacementTarget = this.hScrollBar;
                this.scrollingToolTip.VerticalOffset = 0;
                this.scrollingToolTip.HorizontalOffset = this.dataGrid.ActualWidth / 2;
                this.scrollingToolTip.Content = "Column: " + startColumn.Text;
                this.scrollingToolTip.IsOpen = true;
            }
        }

        void dataGrid1_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            pressedKey = e.Key;
        }
 
        // Deletes the value if the pressed key is the "Del" key.
        void dataGrid1_CellEditorActivated(object sender, CellEventArgs args)
        {
            if (pressedKey == Key.Delete)
            {
                this.dataGrid.CloseEditor(true);
                this.dataGrid.CellsArea.SetCellValue(args.Cell.RowItem, args.Cell.ColumnItem, "");
                this.dataGrid.Refresh();
                return;
            }

            this.textBox = args.Cell.EditorElement as TextBox;
            if (this.textBox != null)
            {
               this.textBox.KeyDown += new KeyEventHandler(textBox_KeyDown);
               this.textBox.TextChanged += new TextChangedEventHandler(textBox_TextChanged);

               SetInitialValue(args.Cell);                
            }
        }

        // Set the TextBox's value to the pressed key value.
        private void SetInitialValue(GridCell cell)
        {
            object value = this.dataGrid.CellsArea.GetCellValue(cell.RowItem, cell.ColumnItem);
           
            int number = 0;
            
            switch (pressedKey)
            {
                case Key.D1:
                case Key.NumPad1:
                    number = 1;
                    break;
                case Key.D2:
                case Key.NumPad2:
                    number = 2;
                    break;
                case Key.D3:
                case Key.NumPad3:
                    number = 3;
                    break;
                case Key.NumPad4:
                case Key.D4:
                    number = 4;
                    break;
                case Key.NumPad5:
                case Key.D5:
                    number = 5;
                    break;
                case Key.NumPad6:
                case Key.D6:
                    number = 6;
                    break;
                case Key.NumPad7:
                case Key.D7:
                    number = 7;
                    break;
                case Key.NumPad8:
                case Key.D8:
                    number = 8;
                    break;
                case Key.NumPad9:
                case Key.D9:
                    number = 9;
                    break;
            }

            if (number > 0)
            {
                this.textBox.Text = this.textBox.Text + number;
                this.textBox.SelectionStart = this.textBox.Text.Length;
            }

            if ((int)pressedKey >= 44 && (int)pressedKey <= 69)
            {
                this.textBox.Text = this.textBox.Text + pressedKey.ToString().ToLower();
                this.textBox.SelectionStart = this.textBox.Text.Length;
            }
        }

        void textBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (e.UndoAction == UndoAction.Create && String.IsNullOrEmpty(this.textBox.Text))
            {
                SetInitialValue(this.dataGrid.CellsArea.EditCell);         
            }
        }

        // Closes the TextBox editor when the user presses Enter, Tab or Escape keys.
        // Enter and Tab keys will close the editor and save the edited value, but the Esc
        // key will cancel the changes.
        void textBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter || e.Key == Key.Tab)
            {
                this.dataGrid.CloseEditor(false);
                e.Handled = true;
            }
            else if (e.Key == Key.Escape)
            {
                this.dataGrid.CloseEditor(true);
                e.Handled = true;
            }
        }

        void dataGrid1_CellEditorDeActivated(object sender, CellEventArgs args)
        {
            this.textBox = this.dataGrid.CellsArea.EditCell.EditorElement as TextBox;

            dataGrid.CellsArea.SetCellValue(args.Cell.RowItem, args.Cell.ColumnItem, this.textBox.Text);

            this.pressedKey = Key.D0;
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);
            dataGrid.CellEditorDeActivated -= new VIBlend.WPF.Controls.DataGrid.CellEventHandler(dataGrid1_CellEditorDeActivated);
            dataGrid.CellEditorActivated -= new VIBlend.WPF.Controls.DataGrid.CellEventHandler(dataGrid1_CellEditorActivated);
            dataGrid.PreviewKeyDown -= new KeyEventHandler(dataGrid1_PreviewKeyDown);

            hScrollBar.ValueChanged -= new RoutedPropertyChangedEventHandler<double>(hScrollBar_ValueChanged);
            vScrollBar.ValueChanged -= new RoutedPropertyChangedEventHandler<double>(vScrollBar_ValueChanged);
            hScrollBar.LostMouseCapture -= new MouseEventHandler(hScrollBar_LostMouseCapture);
            vScrollBar.LostMouseCapture -= new MouseEventHandler(vScrollBar_LostMouseCapture);

            this.dataGrid.CellMouseClick -= new VIBlend.WPF.Controls.DataGrid.CellMouseButtonEventHandler(dataGrid_CellMouseClick);
            this.dataGrid.NavigationKeyDown -= new KeyEventHandler(dataGrid_NavigationKeyDown);
            this.dataGrid.MouseMove -= new MouseEventHandler(dataGrid_MouseMove);

            this.timer = null;
            this.scrollingToolTip = null;
            this.dataGrid.Dispose();
            this.dataGrid = null;
        }
    } // class CellEditing


}
